package com.school.sports.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.school.sports.entity.Referee;
import com.school.sports.entity.RefereeAssignment;
import com.school.sports.entity.User;
import com.school.sports.service.RefereeService;
import com.school.sports.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 裁判管理控制器
 * 提供裁判信息管理、分配、执裁记录等功能
 */
@Slf4j
@RestController
@RequestMapping("/api/referees")
public class RefereeController {

    @Autowired
    private RefereeService refereeService;

    /**
     * 分页查询裁判列表
     * @param currentPage 当前页码
     * @param pageSize 每页大小
     * @param userId 用户ID
     * @param level 裁判等级
     * @param qualifiedItems 可执裁项目类型
     * @param userName 用户姓名（模糊查询）
     * @return 分页结果
     */
    @GetMapping("/page/{currentPage}/{pageSize}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<IPage<Referee>> getRefereePage(
            @PathVariable("currentPage") Integer currentPage,
            @PathVariable("pageSize") Integer pageSize,
            @RequestParam(value = "userId", required = false) Long userId,
            @RequestParam(value = "level", required = false) String level,
            @RequestParam(value = "qualifiedItems", required = false) String qualifiedItems,
            @RequestParam(value = "userName", required = false) String userName) {

        log.info("分页查询裁判列表，当前页码：{}，每页条数：{}，查询条件：userId={}, level={}, qualifiedItems={}, userName={}",
                currentPage, pageSize, userId, level, qualifiedItems, userName);

        try {
            Page<Referee> page = new Page<>(currentPage, pageSize);
            LambdaQueryWrapper<Referee> queryWrapper = new LambdaQueryWrapper<>();

            // 构建查询条件
            queryWrapper.eq(userId != null, Referee::getUserId, userId)
                    .eq(StringUtils.hasText(level), Referee::getLevel, level)
                    .like(StringUtils.hasText(qualifiedItems), Referee::getQualifiedItems, qualifiedItems)
                    .orderByDesc(Referee::getCreatedAt);

            IPage<Referee> refereePage = refereeService.page(page, queryWrapper);
            log.info("查询裁判列表成功，共{}条记录", refereePage.getTotal());
            return Result.success(refereePage);
        } catch (Exception e) {
            log.error("查询裁判列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 根据ID查询裁判详情
     * @param refereeId 裁判ID
     * @return 裁判详情
     */
    @GetMapping("/{refereeId}")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<Referee> getRefereeById(@PathVariable("refereeId") Long refereeId) {
        log.info("查询裁判详情，裁判ID：{}", refereeId);

        if (refereeId == null || refereeId <= 0) {
            return Result.fail("裁判ID无效");
        }

        try {
            Referee referee = refereeService.getRefereeWithDetails(refereeId);
            if (referee == null) {
                return Result.fail("裁判不存在");
            }
            log.info("查询裁判详情成功，裁判ID：{}", refereeId);
            return Result.success(referee);
        } catch (Exception e) {
            log.error("查询裁判详情异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 添加裁判信息
     * @param referee 裁判信息
     * @return 操作结果
     */
    @PostMapping
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> addReferee(@Valid @RequestBody Referee referee) {
        log.info("添加裁判：用户ID={}，等级={}，可执裁项目={}",
                referee.getUserId(), referee.getLevel(), referee.getQualifiedItems());

        try {
            boolean success = refereeService.addReferee(referee);
            if (success) {
                log.info("添加裁判成功");
                return Result.success("添加成功");
            } else {
                return Result.fail("添加失败，用户可能已经是裁判");
            }
        } catch (Exception e) {
            log.error("添加裁判异常：{}", e.getMessage(), e);
            return Result.fail("添加失败：" + e.getMessage());
        }
    }

    /**
     * 更新裁判信息
     * @param referee 裁判信息
     * @return 操作结果
     */
    @PutMapping
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<String> updateReferee(@Valid @RequestBody Referee referee) {
        log.info("更新裁判信息：ID={}", referee.getId());

        try {
            // 权限检查：只有管理员和老师可以修改其他裁判信息，裁判只能修改自己的信息
            User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            if (!"管理员".equals(currentUser.getRole()) && !"老师".equals(currentUser.getRole())) {
                if (!currentUser.getId().equals(referee.getUserId())) {
                    return Result.fail("无权限修改其他裁判信息");
                }
            }

            boolean success = refereeService.updateReferee(referee);
            if (success) {
                log.info("更新裁判成功");
                return Result.success("更新成功");
            } else {
                return Result.fail("更新失败");
            }
        } catch (Exception e) {
            log.error("更新裁判异常：{}", e.getMessage(), e);
            return Result.fail("更新失败：" + e.getMessage());
        }
    }

    /**
     * 删除裁判
     * @param refereeId 裁判ID
     * @return 操作结果
     */
    @DeleteMapping("/{refereeId}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> deleteReferee(@PathVariable("refereeId") Long refereeId) {
        log.info("删除裁判，ID：{}", refereeId);

        if (refereeId == null || refereeId <= 0) {
            return Result.fail("裁判ID无效");
        }

        try {
            boolean success = refereeService.deleteReferee(refereeId);
            if (success) {
                log.info("删除裁判成功");
                return Result.success("删除成功");
            } else {
                return Result.fail("删除失败，该裁判可能有未完成的分配任务");
            }
        } catch (Exception e) {
            log.error("删除裁判异常：{}", e.getMessage(), e);
            return Result.fail("删除失败：" + e.getMessage());
        }
    }

    /**
     * 批量删除裁判
     * @param refereeIds 裁判ID列表
     * @return 操作结果
     */
    @DeleteMapping("/batch")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> batchDeleteReferees(@RequestBody List<Long> refereeIds) {
        log.info("批量删除裁判，裁判ID列表：{}", refereeIds);

        if (refereeIds == null || refereeIds.isEmpty()) {
            return Result.fail("请选择要删除的裁判");
        }

        try {
            boolean success = refereeService.batchDeleteReferees(refereeIds);
            if (success) {
                log.info("批量删除裁判成功，共{}条记录", refereeIds.size());
                return Result.success("批量删除成功");
            } else {
                return Result.fail("批量删除部分失败，请检查是否有未完成的分配任务");
            }
        } catch (Exception e) {
            log.error("批量删除裁判异常：{}", e.getMessage(), e);
            return Result.fail("批量删除失败：" + e.getMessage());
        }
    }

    /**
     * 获取所有裁判等级
     * @return 裁判等级列表
     */
    @GetMapping("/levels")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判', '学生')")
    public Result<List<String>> getRefereeLevels() {
        log.info("获取裁判等级列表");

        try {
            List<String> levels = refereeService.getAllRefereeLevels();
            log.info("获取裁判等级列表成功，共{}种等级", levels.size());
            return Result.success(levels);
        } catch (Exception e) {
            log.error("获取裁判等级列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 根据项目类型获取可用裁判
     * @param projectType 项目类型
     * @return 可用裁判列表
     */
    @GetMapping("/available/{projectType}")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<Referee>> getAvailableReferees(@PathVariable("projectType") String projectType) {
        log.info("根据项目类型查询可用裁判，项目类型：{}", projectType);

        try {
            List<Referee> referees = refereeService.getAvailableRefereesByProjectType(projectType);
            log.info("查询可用裁判成功，共{}条记录", referees.size());
            return Result.success(referees);
        } catch (Exception e) {
            log.error("查询可用裁判异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 分配裁判到项目
     * @param assignment 分配信息
     * @return 操作结果
     */
    @PostMapping("/assign")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> assignReferee(@Valid @RequestBody RefereeAssignment assignment) {
        log.info("分配裁判到项目：裁判ID={}，项目ID={}，轮次={}",
                assignment.getRefereeId(), assignment.getProjectId(), assignment.getRound());

        try {
            // 检查分配冲突
            if (refereeService.hasAssignmentConflict(assignment.getRefereeId(),
                    assignment.getProjectId(), assignment.getRound())) {
                return Result.fail("该裁判在该时间段已有分配任务");
            }

            boolean success = refereeService.assignRefereeToProject(
                    assignment.getRefereeId(), assignment.getProjectId(), assignment.getRound());
            if (success) {
                log.info("分配裁判成功");
                return Result.success("分配成功");
            } else {
                return Result.fail("分配失败，请检查裁判和项目状态");
            }
        } catch (Exception e) {
            log.error("分配裁判异常：{}", e.getMessage(), e);
            return Result.fail("分配失败：" + e.getMessage());
        }
    }

    /**
     * 批量分配裁判
     * @param assignments 分配列表
     * @return 操作结果
     */
    @PostMapping("/batch-assign")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> batchAssignReferees(@RequestBody List<RefereeAssignment> assignments) {
        log.info("批量分配裁判，分配数量：{}", assignments.size());

        if (assignments == null || assignments.isEmpty()) {
            return Result.fail("请提供分配信息");
        }

        try {
            boolean success = refereeService.batchAssignReferees(assignments);
            if (success) {
                log.info("批量分配裁判成功");
                return Result.success("批量分配成功");
            } else {
                return Result.fail("批量分配部分失败，请检查分配冲突");
            }
        } catch (Exception e) {
            log.error("批量分配裁判异常：{}", e.getMessage(), e);
            return Result.fail("批量分配失败：" + e.getMessage());
        }
    }

    /**
     * 裁判接受分配
     * @param assignmentId 分配ID
     * @return 操作结果
     */
    @PutMapping("/assignments/{assignmentId}/accept")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<String> acceptAssignment(@PathVariable("assignmentId") Long assignmentId) {
        log.info("裁判接受分配，分配ID：{}", assignmentId);

        try {
            // 权限检查：裁判只能接受自己的分配
            User currentUser = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
            if ("裁判".equals(currentUser.getRole())) {
                // 需要验证该分配是否属于当前裁判
                // 这里简化处理，实际应该在service层验证
            }

            boolean success = refereeService.acceptAssignment(assignmentId);
            if (success) {
                log.info("接受分配成功");
                return Result.success("已接受分配");
            } else {
                return Result.fail("接受失败，请检查分配状态");
            }
        } catch (Exception e) {
            log.error("接受分配异常：{}", e.getMessage(), e);
            return Result.fail("接受失败：" + e.getMessage());
        }
    }

    /**
     * 裁判拒绝分配
     * @param assignmentId 分配ID
     * @param reason 拒绝原因
     * @return 操作结果
     */
    @PutMapping("/assignments/{assignmentId}/reject")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<String> rejectAssignment(
            @PathVariable("assignmentId") Long assignmentId,
            @RequestParam("reason") String reason) {

        log.info("裁判拒绝分配，分配ID：{}，拒绝原因：{}", assignmentId, reason);

        try {
            boolean success = refereeService.rejectAssignment(assignmentId, reason);
            if (success) {
                log.info("拒绝分配成功");
                return Result.success("已拒绝分配");
            } else {
                return Result.fail("拒绝失败，请检查分配状态");
            }
        } catch (Exception e) {
            log.error("拒绝分配异常：{}", e.getMessage(), e);
            return Result.fail("拒绝失败：" + e.getMessage());
        }
    }

    /**
     * 获取裁判分配列表
     * @param refereeId 裁判ID
     * @return 分配列表
     */
    @GetMapping("/{refereeId}/assignments")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<List<RefereeAssignment>> getRefereeAssignments(@PathVariable("refereeId") Long refereeId) {
        log.info("查询裁判分配列表，裁判ID：{}", refereeId);

        try {
            List<RefereeAssignment> assignments = refereeService.getAssignmentsByRefereeId(refereeId);
            log.info("查询裁判分配列表成功，共{}条记录", assignments.size());
            return Result.success(assignments);
        } catch (Exception e) {
            log.error("查询裁判分配列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取项目分配列表
     * @param projectId 项目ID
     * @return 分配列表
     */
    @GetMapping("/projects/{projectId}/assignments")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<List<RefereeAssignment>> getProjectAssignments(@PathVariable("projectId") Long projectId) {
        log.info("查询项目分配列表，项目ID：{}", projectId);

        try {
            List<RefereeAssignment> assignments = refereeService.getAssignmentsByProjectId(projectId);
            log.info("查询项目分配列表成功，共{}条记录", assignments.size());
            return Result.success(assignments);
        } catch (Exception e) {
            log.error("查询项目分配列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取待确认的分配列表
     * @param refereeId 裁判ID（可选）
     * @return 待确认分配列表
     */
    @GetMapping("/assignments/pending")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<List<RefereeAssignment>> getPendingAssignments(
            @RequestParam(value = "refereeId", required = false) Long refereeId) {

        log.info("查询待确认分配列表，裁判ID：{}", refereeId);

        try {
            List<RefereeAssignment> assignments = refereeService.getPendingAssignments(refereeId);
            log.info("查询待确认分配列表成功，共{}条记录", assignments.size());
            return Result.success(assignments);
        } catch (Exception e) {
            log.error("查询待确认分配列表异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 自动分配裁判
     * @param projectId 项目ID
     * @param round 轮次
     * @param requiredCount 需要的裁判数量
     * @return 操作结果
     */
    @PostMapping("/auto-assign")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> autoAssignReferees(
            @RequestParam("projectId") Long projectId,
            @RequestParam("round") Integer round,
            @RequestParam("requiredCount") Integer requiredCount) {

        log.info("自动分配裁判：项目ID={}，轮次={}，需要数量={}", projectId, round, requiredCount);

        try {
            boolean success = refereeService.autoAssignReferees(projectId, round, requiredCount);
            if (success) {
                log.info("自动分配裁判成功");
                return Result.success("自动分配成功");
            } else {
                return Result.fail("自动分配失败，可能没有足够的可用裁判");
            }
        } catch (Exception e) {
            log.error("自动分配裁判异常：{}", e.getMessage(), e);
            return Result.fail("自动分配失败：" + e.getMessage());
        }
    }

    /**
     * 获取裁判执裁记录
     * @param refereeId 裁判ID
     * @param projectId 项目ID（可选）
     * @return 执裁记录列表
     */
    @GetMapping("/{refereeId}/records")
    @PreAuthorize("hasAnyRole('管理员', '老师', '裁判')")
    public Result<List<Map<String, Object>>> getRefereeRecords(
            @PathVariable("refereeId") Long refereeId,
            @RequestParam(value = "projectId", required = false) Long projectId) {

        log.info("查询裁判执裁记录，裁判ID：{}，项目ID：{}", refereeId, projectId);

        try {
            List<Map<String, Object>> records = refereeService.getRefereeRecords(refereeId, projectId);
            log.info("查询裁判执裁记录成功，共{}条记录", records.size());
            return Result.success(records);
        } catch (Exception e) {
            log.error("查询裁判执裁记录异常：{}", e.getMessage(), e);
            return Result.fail("查询失败：" + e.getMessage());
        }
    }

    /**
     * 获取裁判统计信息
     * @param refereeId 裁判ID（可选）
     * @return 统计信息
     */
    @GetMapping("/statistics")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<Map<String, Object>> getRefereeStatistics(
            @RequestParam(value = "refereeId", required = false) Long refereeId) {

        log.info("获取裁判统计信息，裁判ID：{}", refereeId);

        try {
            Map<String, Object> statistics = refereeService.getRefereeStatistics(refereeId);
            log.info("获取裁判统计信息成功");
            return Result.success(statistics);
        } catch (Exception e) {
            log.error("获取裁判统计信息异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 获取推荐裁判列表
     * @param projectId 项目ID
     * @param round 轮次
     * @param limit 限制数量
     * @return 推荐裁判列表
     */
    @GetMapping("/recommendations")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<Referee>> getRecommendedReferees(
            @RequestParam("projectId") Long projectId,
            @RequestParam("round") Integer round,
            @RequestParam(value = "limit", defaultValue = "5") Integer limit) {

        log.info("获取推荐裁判列表：项目ID={}，轮次={}，限制数量={}", projectId, round, limit);

        try {
            List<Referee> referees = refereeService.getRecommendedReferees(projectId, round, limit);
            log.info("获取推荐裁判列表成功，共{}条记录", referees.size());
            return Result.success(referees);
        } catch (Exception e) {
            log.error("获取推荐裁判列表异常：{}", e.getMessage(), e);
            return Result.fail("获取失败：" + e.getMessage());
        }
    }

    /**
     * 导出裁判信息
     * @param refereeIds 裁判ID列表
     * @return 导出数据
     */
    @PostMapping("/export")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<List<Map<String, Object>>> exportReferees(@RequestBody List<Long> refereeIds) {
        log.info("导出裁判信息，裁判ID列表：{}", refereeIds);

        try {
            List<Map<String, Object>> exportData = refereeService.exportRefereeInfo(refereeIds);
            log.info("导出裁判信息成功，共{}条记录", exportData.size());
            return Result.success(exportData);
        } catch (Exception e) {
            log.error("导出裁判信息异常：{}", e.getMessage(), e);
            return Result.fail("导出失败：" + e.getMessage());
        }
    }

    /**
     * 激活裁判身份
     * @param userId 用户ID
     * @param level 裁判等级
     * @param qualifiedItems 可执裁项目
     * @param experience 执裁经历
     * @return 操作结果
     */
    @PostMapping("/activate")
    @PreAuthorize("hasAnyRole('管理员', '老师')")
    public Result<String> activateReferee(
            @RequestParam("userId") Long userId,
            @RequestParam("level") String level,
            @RequestParam("qualifiedItems") String qualifiedItems,
            @RequestParam(value = "experience", required = false) String experience) {

        log.info("激活裁判身份：用户ID={}，等级={}", userId, level);

        try {
            boolean success = refereeService.activateReferee(userId, level, qualifiedItems, experience);
            if (success) {
                log.info("激活裁判身份成功");
                return Result.success("激活成功");
            } else {
                return Result.fail("激活失败，用户可能已经是裁判");
            }
        } catch (Exception e) {
            log.error("激活裁判身份异常：{}", e.getMessage(), e);
            return Result.fail("激活失败：" + e.getMessage());
        }
    }

    /**
     * 校验状态合法性
     */
    private boolean isValidStatus(String status) {
        return Arrays.asList("待确认", "已接受", "已拒绝").contains(status);
    }
}